﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Caching;
using System.Collections;

namespace NetOpen_System.Component
{
    public sealed class GlobesCache
    {
        /// <summary>
        /// 日期因数（一天包含的秒数）
        /// </summary>
        public static readonly int DayFactor = 86400;
        /// <summary>
        /// 小时因数（一小时包含的秒数）
        /// </summary>
        public static readonly int HourFactor = 3600;
        /// <summary>
        /// 分钟因数（一分钟包含的秒数）
        /// </summary>
        public static readonly int MinuteFactor = 60;
        private static readonly Cache _cache;

        private static string m_prefix = "NetOpen_System.Component.GlobesCachekey";

        static GlobesCache()
        {
            if (HttpContext.Current != null)
                _cache = HttpContext.Current.Cache;
            else
                _cache = HttpRuntime.Cache;
        }
        /// <summary>
        /// 
        /// </summary>
        private GlobesCache()
        {
        }

        #region 私有方法

        private static Regex CachekeyPrefixRegex()
        {
            return new Regex(string.Format(@"^({0}_)([\w]*)", m_prefix)
                , RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
        }

        #endregion

        #region 获取对象

        /// <summary>
        /// 获取包含前缀的缓存键
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <returns>带前缀的缓存键</returns>
        public static string GetCachekeyWithPrefix(string key)
        {
            return string.Format("{0}_{1}", m_prefix, key);
        }

        /// <summary>
        /// 获取缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <returns>缓存对象</returns>
        public static object Get(string key)
        {
            if (key == null || key == string.Empty) return null;
            return _cache[GetCachekeyWithPrefix(key)];
        }

        #endregion


        #region 移除＆清理
        /// <summary>
        /// 按正则匹配移除缓存
        /// </summary>
        /// <param name="pattern">与不含前缀的缓存键匹配的表达式</param>
        public static void RemoveByPattern(string pattern)
        {
            IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
            Regex regexKey = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
            Regex regPrefix = CachekeyPrefixRegex();

            while (CacheEnum.MoveNext())
            {
                string a = CacheEnum.Key.ToString();
                if (regPrefix.IsMatch(a))
                {
                    string b = regPrefix.Replace(a, "$2");
                    if (b != null && b != string.Empty && regexKey.IsMatch(b))
                        _cache.Remove(a);
                }
            }
        }

        /// <summary>
        /// 移除缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        public static void Remove(string key)
        {
            if (key == null || key == string.Empty) return;
            string s = GetCachekeyWithPrefix(key);
            _cache.Remove(s);
        }
        /// <summary>
        /// 清理全部缓存
        /// </summary>
        public static void ClearAll()
        {
            IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
            ArrayList al = new ArrayList();
            while (CacheEnum.MoveNext())
            {
                al.Add(CacheEnum.Key);
            }

            foreach (string key in al)
            {
                _cache.Remove(key);
            }
        }

        /// <summary>
        /// 清理当前监控器对应缓存键前缀的缓存
        /// </summary>
        public static void Clear()
        {
            Regex regPrefix = CachekeyPrefixRegex();
            IDictionaryEnumerator CacheEnum = _cache.GetEnumerator();
            ArrayList al = new ArrayList();
            while (CacheEnum.MoveNext())
            {
                if (regPrefix.IsMatch(CacheEnum.Key.ToString()))
                    al.Add(CacheEnum.Key);
            }

            foreach (string key in al)
            {
                _cache.Remove(key);
            }
        }

        #endregion


        #region 创建缓存对象

        /// <summary>
        /// 添加缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        /// <param name="dep">依存项</param>
        public static void Insert(string key, object obj, CacheDependency dep)
        {
            Insert(key, obj, dep, MinuteFactor * 3);
        }

        /// <summary>
        /// 添加缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        /// <param name="seconds">对象过期时间间隔（单位：秒）。</param>
        public static void Insert(string key, object obj, int seconds)
        {
            Insert(key, obj, null, seconds);
        }

        /// <summary>
        /// 添加缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        /// <param name="dep">依存项</param>
        /// <param name="seconds">对象过期时间间隔（单位：秒）。</param>
        public static void Insert(string key, object obj, CacheDependency dep, int seconds)
        {
            Insert(key, obj, dep, seconds, CacheItemPriority.Normal);
        }


        /// <summary>
        /// 添加缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        /// <param name="dep">依存项</param>
        /// <param name="seconds">对象过期时间间隔（单位：秒）。</param>
        /// <param name="priority">相对优先级</param>
        public static void Insert(string key, object obj, CacheDependency dep, int seconds, CacheItemPriority priority)
        {
            if (key == null || key == string.Empty || obj == null)
                return;
            _cache.Insert(GetCachekeyWithPrefix(key), obj, dep, DateTime.Now.AddSeconds(seconds), TimeSpan.Zero, priority, null);
        }


        /// <summary>
        /// 添加永久缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        public static void Max(string key, object obj)
        {
            Max(key, obj, null);
        }

        /// <summary>
        /// 添加永久缓存对象
        /// </summary>
        /// <param name="key">不含前缀的缓存键</param>
        /// <param name="obj">缓存对象</param>
        /// <param name="dep">依存项</param>
        public static void Max(string key, object obj, CacheDependency dep)
        {
            if (key == null || key == string.Empty || obj == null)
                return;
            _cache.Insert(GetCachekeyWithPrefix(key), obj, dep, DateTime.MaxValue, TimeSpan.Zero, CacheItemPriority.AboveNormal, null);

        }


        #endregion
    }
}
